using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
using System.Threading;
using System.Globalization;
using System.Xml;

using Infragistics.Windows.DataPresenter;

using ViewOnCore.Helper.WPF;
using ViewOnCore.Helper.Collection;
using ViewOnCore;
using ViewOnCore.HostContract;
using ViewOnCore.HostContract.Media;
using ViewOnCore.Device;
using ViewOnCore.Visual;

using UI.Control;

namespace MediaDesktopPlayerAddIn
{

    // Encoding :
    //          http://www.mediasoftpro.com/index.html
    public partial class MediaDesktopPlayer : VisualPart
    {

        #region Variables

        private Desktop _desktop;

        private List<VideoLibraryDialog> _videoLibraries = new List<VideoLibraryDialog>(0);
        private List<VideoWindow> _videoWindows = new List<VideoWindow>(0);

        private bool _isFirstActivation = true;

        #endregion

        #region Constructor

        public MediaDesktopPlayer()
        {
            InitializeComponent();

            MediaTypeTags.Add("MediaDesktop");

            //----
            _desktop = new Desktop("MediaDesktop", childWindowsCanvas, contentPresenter);
            _desktop.SupportSelection = true;

            btnLibrary.Click += new RoutedEventHandler(btnLibrary_Click);
            txtZoom.TextChanged += new TextChangedEventHandler(txtZoom_TextChanged);
            sliZoom.ValueChanged += new RoutedPropertyChangedEventHandler<double>(sliZoom_ValueChanged);

            //----
            btnExpand.Click += new RoutedEventHandler(btnExpand_Click);

            //----
            this.AllowDrop = true;
            this.Drop += new DragEventHandler(VideoPart_Drop);
            this.DragOver += new DragEventHandler(VideoPart_DragOver);

            //----
            this.PreviewMouseRightButtonDown += new MouseButtonEventHandler(VideoPart_PreviewMouseRightButtonDown);

            ContextMenu menu = (ContextMenu)FindResource("VideoPartContextMenu");
            ((MenuItem)menu.Items[0]).Click += new RoutedEventHandler(VideoPart_AlignToGrid_Click);
            ((MenuItem)menu.Items[1]).Click += new RoutedEventHandler(VideoPart_OrganizeToGrid_Click);
            ((MenuItem)menu.Items[3]).Click += new RoutedEventHandler(VideoPart_RemoveSelectedDesktopIcons_Click);

            //---- Set up
            sliZoom.Value = Host.SettingsService.VideoDesktopZoom;

            Host.MediaService.MediaSelectionChanged += new EventHandler(MediaService_MediaSelectionChanged);
        }

        #endregion

        #region Properties

        override public string Handle
        {
            get
            {
                return "ViewOnTv_VideoPlayerAddIn";
            }
        }

        #endregion

        #region VisualPart : management

        override public VisualPartDisplayInformation OnRequestDisplayInformation(VisualPartDisplayInformation currentDisplayInformation, VisualPartDisplayInformation leavedDisplayInformation)
        {
            VisualPartDisplayInformation newDisplayInformation = new VisualPartDisplayInformation();

            return newDisplayInformation;
        }

        #endregion

        #region VisualPart : OnPreDisplay/OnPostDisplay/OnPreHidde/OnRequestVisualAddIn

        public override void OnPreDisplay(Control container)
        {
            base.OnPreDisplay(container);

            //---- Pause all the music
            if (Host.MediaService.MediaPlayStatus == MediaPlayStatus.Play)
                Host.MediaService.Stop();
        }

        override public void OnPostDisplay(Control container)
        {
            RestoreDesktop();
        }

        public override void OnPreHide(Control container)
        {
            base.OnPreHide(container);

            //---- Pause all the videos
            StandByAllVideos();
        }

        override public VisualPartPriority OnRequestVisualPartPriority()
        {
            if (Host.VisualService.VisualPartMode != VisualPartMode.Normal)
                return VisualPartPriority.None;

            if (Host.MediaService.CurrentMediaDeviceFeature.MediaTypeTags.Contains("MediaDesktop"))
                return VisualPartPriority.Normal;

            return VisualPartPriority.None;
        }

        #endregion

        #region RestoreDesktop

        private void RestoreDesktop()
        {
            if (!_isFirstActivation)
                return;
            _isFirstActivation = false;

            XmlNodeList nodes = _desktop.FindXml();

            //---- Show everything that has been saved
            foreach (XmlNode node in nodes)
            {
                MediaFolder folder = FindFolder(XmlConvert.DecodeName(node.Attributes["Key"].Value));

                VideoLibraryDialog dialog = CreateLibraryDialog(folder, ChildWindowDecoratorState.Closed, new Point(0, 0));
                dialog.childWindowDecorator.LoadXml();

                ShowLibraryDialog(dialog);
            }
        }

        private MediaFolder FindFolder(string key)
        {
            if (key == "Video$Library")
                return null;

            string[] folders = key.Split('$');
            ExtObservableCollection<MediaData> medias = Host.MediaService.CurrentMediaDeviceFeature.MediaDatas;

            MediaFolder currentFolder = null;
            foreach (string folder in folders)
                foreach (MediaData media in medias)
                    if (media is MediaFolder)
                    {
                        string title = media.Title.Replace(' ', '%');
                        if (title == folder)
                        {
                            currentFolder = media as MediaFolder;
                            medias = ((MediaFolder)media).MediaDatas;
                            break;
                        }
                    }

            return currentFolder;
        }

        #endregion

        #region Tag panel : Expand / Collapse

        private bool _isExpanded = true;
        private double collapseHeight = -1;

        void btnExpand_Click(object sender, RoutedEventArgs e)
        {
            if (_isExpanded)
                Collapse();
            else
                Expand();

            _isExpanded = !_isExpanded;
        }

        void Collapse()
        {
            //if (collapseHeight < 0)
            collapseHeight = griMain.RowDefinitions[2].ActualHeight;

            GridLengthAnimation gla = new GridLengthAnimation(GridUnitType.Pixel);
            gla.From = new GridLength(collapseHeight, GridUnitType.Pixel);
            gla.To = new GridLength(18, GridUnitType.Pixel); ;
            gla.Duration = new TimeSpan(0, 0, 0, 0, 300);
            griMain.RowDefinitions[2].BeginAnimation(RowDefinition.HeightProperty, gla);

            imgCollapse.Visibility = Visibility.Collapsed;
            imgExpand.Visibility = Visibility.Visible;
        }

        void Expand()
        {
            GridLengthAnimation gla = new GridLengthAnimation(GridUnitType.Pixel);
            gla.From = new GridLength(18, GridUnitType.Pixel);
            gla.To = new GridLength(collapseHeight, GridUnitType.Pixel); ;
            gla.Duration = new TimeSpan(0, 0, 0, 0, 300);
            griMain.RowDefinitions[2].BeginAnimation(RowDefinition.HeightProperty, gla);

            imgExpand.Visibility = Visibility.Collapsed;
            imgCollapse.Visibility = Visibility.Visible;
        }

        #endregion

        #region RefreshTag

        public void RefreshTag(List<Video> videos)
        {
            videoTag.Refresh(videos);
        }

        #endregion

        #region Create Library dialog

        public VideoLibraryDialog CreateLibraryDialog(MediaFolder folder, ChildWindowDecoratorState windowState, Point initialPosition)
        {
            VideoLibraryDialog library = new VideoLibraryDialog(this, folder);
            library.childWindowDecorator.WindowState = windowState;
            library.childWindowDecorator.StartupPosition = WindowStartupLocation.Manual;
            _videoLibraries.Add(library);

            Canvas.SetLeft(library, initialPosition.X);
            Canvas.SetTop(library, initialPosition.Y);

            if (windowState == ChildWindowDecoratorState.DesktopIcon)
            {
                Canvas.SetLeft(library.childWindowDecorator.DesktopIcon, initialPosition.X);
                Canvas.SetTop(library.childWindowDecorator.DesktopIcon, initialPosition.Y);
            }

            library.Width = 550;
            library.Height = 350;

            return library;
        }

        #endregion

        #region FindVideoLibraryDialog

        public VideoLibraryDialog FindVideoLibraryDialog(MediaFolder folder)
        {
            foreach (FrameworkElement element in _desktop.ChildWindowsCanvas.Children)
                if (element is VideoLibraryDialog)
                    if (((VideoLibraryDialog)element).RootFolder == folder)
                        return (VideoLibraryDialog)element;

            return null;
        }

        #endregion

        #region ShowLibraryDialog

        public void ShowLibraryDialog(VideoLibraryDialog libraryDialog)
        {
            libraryDialog.childWindowDecorator.Show(_desktop);
        }

        #endregion

        #region Show library

        void btnLibrary_Click(object sender, RoutedEventArgs e)
        {
            VideoLibraryDialog dialog = FindVideoLibraryDialog(null);
            if (dialog == null)
                dialog = CreateLibraryDialog(null, ChildWindowDecoratorState.Closed, new Point());

            if (dialog.childWindowDecorator.WindowState == ChildWindowDecoratorState.Opened ||
                dialog.childWindowDecorator.WindowState == ChildWindowDecoratorState.DesktopIcon)
                dialog.childWindowDecorator.BringToTop();
            else
                dialog.childWindowDecorator.Show(_desktop);

            dialog.childWindowDecorator.UpdateXml();
        }

        #endregion

        #region StandByAllVideos

        /// <summary>
        /// Pause all the videos.
        /// </summary>
        public void StandByAllVideos()
        {
            foreach (VideoWindow window in _videoWindows)
                window.StandBy();
        }

        #endregion

        #region Zoom

        bool _isUpdatingText = false;

        void txtZoom_TextChanged(object sender, TextChangedEventArgs e)
        {
            if (_isUpdatingText)
                return;
            _isUpdatingText = true;

            double zoom;

            if (!Double.TryParse(txtZoom.Text, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out zoom))
            {
                _isUpdatingText = false;
                return;
            }

            if (zoom < 0.1)
                zoom = 0.1;
            if (zoom > 1.5)
                zoom = 1.5;

            if (zoom != sliZoom.Value)
                sliZoom.Value = zoom;

            Host.SettingsService.VideoDesktopZoom = sliZoom.Value;

            _isUpdatingText = false;
        }

        void sliZoom_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            if (_isUpdatingText)
                return;

            txtZoom.Text = sliZoom.Value.ToString("F1", CultureInfo.InvariantCulture);

            Host.SettingsService.VideoDesktopZoom = sliZoom.Value;
        }

        #endregion

        #region ShowVideoWindow

        private void ShowVideoWindow(Video video)
        {
            Dispatcher.BeginInvoke(DispatcherPriority.Normal,
                                    (DelegateInvoker)delegate { AsyncShowVideoWindow(video); });
        }

        private void AsyncShowVideoWindow(Video video)
        {
            //---- Show it
            foreach (VideoWindow window in _videoWindows)
                if (window.Video.Path == video.Path)
                {
                    if (window.childWindowManager.WindowState == ChildWindowDecoratorState.Opened)
                        window.childWindowManager.BringToTop();
                    else
                        window.childWindowManager.Show(_desktop);
                    return;
                }

            //---- Create the new window
            VideoWindow newWindow = new VideoWindow(video);
            _videoWindows.Add(newWindow);
            newWindow.childWindowManager.Closed += new EventHandler(childWindowManager_Closed);
            newWindow.childWindowManager.Show(_desktop);
        }

        #endregion

        #region Drop file on list

        void VideoPart_DragOver(object sender, DragEventArgs e)
        {
            Point mousePosition = e.GetPosition(_desktop.ChildWindowsCanvas);
            if (_desktop.IsMouseOverDekstopElement(mousePosition))
                return;

            //---- Video
            List<MediaData> mediaDatas = e.Data.GetData("ViewOn.Kernel.Media.MediaData", true) as List<MediaData>;
            if (mediaDatas != null)
            {
                e.Handled = true;
                e.Effects = DragDropEffects.Link;
                return;
            }

            //---- Media Folder
            MediaFolder mediaFolder = e.Data.GetData("ViewOn.Kernel.Media.MediaFolder", true) as MediaFolder;
            if (mediaFolder != null)
            {
                e.Handled = true;
                e.Effects = DragDropEffects.Link;
                return;
            }

            //---- File
            string[] filePathInfo = e.Data.GetData("FileDrop", true) as string[];
            if (filePathInfo == null)
            {
                e.Handled = true;
                e.Effects = DragDropEffects.None;
                return;
            }

            foreach (string filePath in filePathInfo)
            {
                if (!Host.MediaService.IsSupportedVideoFile(filePathInfo[0]))
                {
                    e.Handled = true;
                    e.Effects = DragDropEffects.None;
                    return;
                }
            }

            e.Effects = DragDropEffects.Copy;
        }

        void VideoPart_Drop(object sender, DragEventArgs e)
        {
            Point mousePosition = e.GetPosition(_desktop.ChildWindowsCanvas);

            if (_desktop.IsMouseOverDekstopElement(mousePosition))
                return;

            //---- Video
            List<MediaData> mediaDatas = e.Data.GetData("ViewOn.Kernel.Media.MediaData", true) as List<MediaData>;
            if (mediaDatas != null)
            {
                foreach (MediaData media in mediaDatas)
                    if (media is Video)
                        Host.MediaService.PlayMedia(media);
                    else
                    {
                        VideoLibraryDialog dialog = FindVideoLibraryDialog((MediaFolder)media);

                        // Bring it to top
                        if (dialog != null)
                        {
                            dialog.childWindowDecorator.BringToTop();
                            return;
                        }

                        // Create the dialog
                        dialog = CreateLibraryDialog((MediaFolder)media, ChildWindowDecoratorState.DesktopIcon, mousePosition);

                        ShowLibraryDialog(dialog);

                        dialog.childWindowDecorator.UpdateXml();
                    }
                return;
            }

            //---- Media folder
            MediaFolder mediaFolder = e.Data.GetData("ViewOn.Kernel.Media.MediaFolder", true) as MediaFolder;
            if (mediaFolder != null)
            {
                VideoLibraryDialog dialog = FindVideoLibraryDialog(mediaFolder);

                // Bring it to top
                if (dialog != null)
                {
                    dialog.childWindowDecorator.BringToTop();
                    return;
                }

                // Create the dialog
                dialog = CreateLibraryDialog(mediaFolder, ChildWindowDecoratorState.DesktopIcon, mousePosition);

                ShowLibraryDialog(dialog);

                dialog.childWindowDecorator.UpdateXml();

                return;
            }

            //---- File
            string[] filePathInfo = e.Data.GetData("FileDrop", true) as string[];
            if (filePathInfo == null)
                return;

            foreach (string filePath in filePathInfo)
            {
                if (!Host.MediaService.IsSupportedVideoFile(filePath))
                    continue;

                //---- Import the file
                Video video = Video.FromFile(filePath);
                if (video == null)
                    return;

                Host.MediaService.PlayMedia(video);
            }
        }

        #endregion

        #region Context menu

        void VideoPart_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
        {
            Point mousePosition = e.GetPosition(_desktop.ChildWindowsCanvas);
            if (_desktop.IsMouseOverDekstopElement(mousePosition))
                return;

            ContextMenu menu = (ContextMenu)FindResource("VideoPartContextMenu");

            if (_desktop.SelectedDesktopIcons.Count < 1)
            {
                ((MenuItem)menu.Items[3]).IsEnabled = false;
            }
            else
            {
                ((MenuItem)menu.Items[3]).IsEnabled = true;
            }

            menu.IsOpen = true;
        }

        void VideoPart_AlignToGrid_Click(object sender, RoutedEventArgs e)
        {
            _desktop.AlignIconsToGrid();
        }

        void VideoPart_OrganizeToGrid_Click(object sender, RoutedEventArgs e)
        {
            _desktop.OrganizeIconsToGrid();
        }

        void VideoPart_RemoveSelectedDesktopIcons_Click(object sender, RoutedEventArgs e)
        {
            _desktop.RemoveSelectedDesktopIcons();
        }

        #endregion

        #region MediaService : MediaSelectionChanged

        void MediaService_MediaSelectionChanged(object sender, EventArgs e)
        {
            if (!IsActive)
                return;

            Video video = Host.MediaService.CurrentMedia as Video;
            if (video == null)
                return;

            ShowVideoWindow(video);
        }

        #endregion

        #region Event : ChildWindow_Closed

        void childWindowManager_Closed(object sender, EventArgs e)
        {
            VideoWindow window = (VideoWindow)((ChildWindowDecorator)sender).Parent;
            _videoWindows.Remove(window);
        }

        #endregion

    }

}